using System;
using System.Data;
using System.Globalization;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using mojoPortal.Web;
using mojoPortal.Web.UI;
using mojoPortal.Web.Framework;
using mojoPortal.Business;
using mojoPortal.Business.Commerce;
using mojoPortal.Business.WebHelpers.PaymentGateway;
using eStore.Business;
using Resources;
using eStore.Helpers;
using GCheckout.Checkout;
using GCheckout.Util;
using System.Collections;

namespace eStore.UI
{

    public partial class CartPage : mojoBasePage
    {
        protected int pageId = -1;
        protected int moduleId = -1;
        private Store store;
        private CommerceConfiguration commerceConfig;
        private SiteUser siteUser;
        private Cart cart;
        protected CultureInfo currencyCulture = CultureInfo.CurrentCulture;
        private bool canCheckoutWithoutAuthentication;
        private eStoreConfiguration config = new eStoreConfiguration();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!UserCanViewPage(moduleId))
            {
                SiteUtils.RedirectToAccessDeniedPage();
                return;
            }
            LoadSettings();

            if ((store == null) || (store.IsClosed))
            {
                WebUtils.SetupRedirect(this, SiteUtils.GetCurrentPageUrl());
                return;
            }

            SetupCss();
            PopulateLabels();
            ShowCart();
            
        }

        private void ShowCart()
        {
            if (Page.IsPostBack) { return; }

            if ((store == null) || (cart == null)) return;
            using (IDataReader reader = cart.GetItems())
            {
                rptCartItems.DataSource = reader;
                rptCartItems.DataBind();
            }

            litDiscount.Text = StoreHelper.FormatPrice(cart.Discount.ToString(), currencyCulture);
            pnlDiscountAmount.Visible = (cart.Discount > 0);
            litSubTotal.Text = StoreHelper.FormatPrice(cart.SubTotal.ToString(), currencyCulture);
            pnlTotal.Visible = pnlDiscountAmount.Visible;
            decimal totalWithoutTax = cart.SubTotal - cart.Discount;
            litTotal.Text = StoreHelper.FormatPrice(totalWithoutTax.ToString(), currencyCulture);
        }

        void btnApplyDiscount_Click(object sender, EventArgs e)
        {
            string errorMessage;
            if (StoreHelper.ApplyDiscount(store, cart, txtDiscountCode.Text, out errorMessage))
            {
                WebUtils.SetupRedirect(this, Request.RawUrl);
                return;
            }
            lblDiscountError.Text = errorMessage;

        }

        private void SetupPayPalStandardForm()
        {
            if (cart == null) { return; }
            //if (siteUser == null) { return; }

            if (cart.UserGuid == Guid.Empty)
            {
                if (siteUser != null)
                {
                    cart.UserGuid = siteUser.UserGuid;
                    cart.Save();
                }
            }

            //if ((cart.CartProducts.Count == 0)||(cart.OrderTotal == 0))
            //{
            //    litOr.Visible = false;
            //    btnPayPal.Visible = false;
            //    return; 
            //}

            PayPalLog payPalLog = StoreHelper.EnsurePayPalStandardCheckoutLog(cart, store, SiteRoot, pageId, moduleId);
            if (payPalLog == null) return;

            litPayPalFormVariables.Text = StoreHelper.GetCartUploadFormFields(
                payPalLog.RowGuid,
                cart,
                store,
                commerceConfig);

            btnPayPal.PostBackUrl = commerceConfig.PayPalStandardUrl;
        }

        void btnPayPal_Click(object sender, ImageClickEventArgs e)
        {
            if (commerceConfig.PayPalUsePayPalStandard)
            {
                DoPayPalStandardCheckout();
            }
            else
            {
                DoPayPalExpressCeckout();
            }
        }



        private void DoPayPalExpressCeckout()
        {
            PayPalExpressGateway gateway
                = new PayPalExpressGateway(
                    commerceConfig.PayPalAPIUsername,
                    commerceConfig.PayPalAPIPassword,
                    commerceConfig.PayPalAPISignature,
                    commerceConfig.PayPalStandardEmailAddress)
                      {
                          UseTestMode = commerceConfig.PaymentGatewayUseTestMode,
                          MerchantCartId = cart.CartGuid.ToString(),
                          ChargeTotal = cart.OrderTotal
                      };

            string siteRoot = SiteUtils.GetNavigationSiteRoot();
            gateway.ReturnUrl = siteRoot + "/Services/PayPalReturnHandler.ashx";
            gateway.CancelUrl = siteRoot + Request.RawUrl;
            //Currency currency = new Currency(store.DefaultCurrencyId);
            //gateway.CurrencyCode = currency.Code;
            gateway.CurrencyCode = siteSettings.GetCurrency().Code;
            gateway.OrderDescription = store.Name + " " + eStoreResources.OrderHeading;

            gateway.BuyerEmail = cart.OrderInfo.CustomerEmail;
            gateway.ShipToFirstName = cart.OrderInfo.DeliveryFirstName;
            gateway.ShipToLastName = cart.OrderInfo.DeliveryLastName;
            gateway.ShipToAddress = cart.OrderInfo.DeliveryAddress1;
            gateway.ShipToAddress2 = cart.OrderInfo.DeliveryAddress2;
            gateway.ShipToCity = cart.OrderInfo.DeliveryCity;
            gateway.ShipToState = cart.OrderInfo.DeliveryState;
            gateway.ShipToCountry = cart.OrderInfo.DeliveryCountry;
            gateway.ShipToPostalCode = cart.OrderInfo.DeliveryPostalCode;
            gateway.ShipToPhone = cart.OrderInfo.CustomerTelephoneDay;

            // this tells paypal to use the shipping address we pass in
            // rather than what the customer has on file
            // when we implement shippable products we'll do shipping calculations before
            // sending the user to paypal
            //gateway.OverrideShippingAddress = true;

            //commented out the above, we want user to be able to populate shipping info from their paypal account

            bool executed = gateway.CallSetExpressCheckout();
            if (executed)
            {
                //TODO: log the raw response
                if (gateway.PayPalExpressUrl.Length > 0)
                {
                    // record the gateway.PayPalToken
                    PayPalLog payPalLog = new PayPalLog
                                              {
                                                  RawResponse = gateway.RawResponse,
                                                  ProviderName = "eStorePayPalHandler",
                                                  ReturnUrl = siteRoot + Request.RawUrl,
                                                  Token = HttpUtility.UrlDecode(gateway.PayPalToken),
                                                  RequestType = "SetExpressCheckout"
                                              };

                    cart.SerializeCartProducts();
                    payPalLog.SerializedObject = SerializationHelper.SerializeToString(cart);

                    payPalLog.CartGuid = cart.CartGuid;
                    payPalLog.SiteGuid = store.SiteGuid;
                    payPalLog.StoreGuid = store.Guid;
                    payPalLog.UserGuid = cart.UserGuid;

                    payPalLog.Save();

                    Response.Redirect(gateway.PayPalExpressUrl);

                }

            }

        }

        /// <summary>
        /// This is really a fallback method, it will not be executed in normal use because we are setting the postbackurl of the button
        /// to post directly to paypal, so this method should not fire unless somehow the page is manipulated to postback to itself.
        /// In this case, we just consolidate the cart into a buy now button.
        /// </summary>
        private void DoPayPalStandardCheckout()
        {
            PayPalLog payPalLog = new PayPalLog
                                      {
                                          ProviderName = "eStorePayPalHandler",
                                          PDTProviderName = "eStorePayPalPDTHandlerProvider",
                                          IPNProviderName = "eStorePayPalIPNHandlerProvider",
                                          ReturnUrl = SiteRoot +
                                                      "/eStore/OrderDetail.aspx?pageid="
                                                      + pageId.ToInvariantString()
                                                      + "&mid=" + moduleId.ToInvariantString()
                                                      + "&orderid=" + cart.CartGuid,
                                          RequestType = "StandardCheckout"
                                      };

            cart.SerializeCartProducts();
            payPalLog.SerializedObject = SerializationHelper.SerializeToString(cart);
            payPalLog.CartGuid = cart.CartGuid;
            payPalLog.SiteGuid = store.SiteGuid;
            payPalLog.StoreGuid = store.Guid;
            payPalLog.UserGuid = cart.UserGuid;
            payPalLog.CartTotal = cart.OrderTotal;
            payPalLog.CurrencyCode = siteSettings.GetCurrency().Code;

            payPalLog.Save();

            string payPalStandardUrl = StoreHelper.GetBuyNowUrl(
                payPalLog.RowGuid,
                cart,
                store,
                commerceConfig);


            WebUtils.SetupRedirect(this, payPalStandardUrl);

        }

        private void rptCartItems_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            if (cart == null) { return; }

            string strGuid = e.CommandArgument.ToString();
            if (strGuid.Length != 36) { return; }

            Guid itemGuid = new Guid(strGuid);

            switch (e.CommandName)
            {
                case "updateQuantity":
                    int quantity = 1;
                    TextBox txtQty = e.Item.FindControl("txtQuantity") as TextBox;
                    if (txtQty != null)
                    {
                        try
                        {
                            int.TryParse(txtQty.Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out quantity);
                        }
                        catch (ArgumentException) { }
                    }
                    if (quantity > 0)
                    {
                        cart.UpdateCartItemQuantity(itemGuid, quantity);
                    }
                    break;

                case "delete":

                    cart.DeleteItem(itemGuid);
                    cart.ResetCartProducts();
                    cart.RefreshTotals();
                    cart.Save();

                    break;

            }

            StoreHelper.EnsureValidDiscounts(store, cart);

            WebUtils.SetupRedirect(this, Request.RawUrl);

        }

        void btnGoogleCheckout_Click(object sender, ImageClickEventArgs e)
        {
            if (
                (store != null)
                && (cart != null)
                )
            { //&& (IsValidForCheckout()) ?

                const int cartTimeoutInMinutes = 30;

                CheckoutShoppingCartRequest Req = new CheckoutShoppingCartRequest(
                    commerceConfig.GoogleMerchantID,
                    commerceConfig.GoogleMerchantKey,
                    commerceConfig.GoogleEnvironment,
                    siteSettings.GetCurrency().Code,
                    cartTimeoutInMinutes);


                foreach (CartProduct cartProduct in cart.CartProducts)
                {

                    Req.AddItem(
                        cartProduct.Name,
                        string.Empty,
                        cartProduct.ProductPrice,
                        cartProduct.Quantity);
                }

                //Req.AddMerchantCalculatedShippingMethod
                //Req.AnalyticsData
                //Req.ContinueShoppingUrl
                //Req.EditCartUrl

                //Req.RequestInitialAuthDetails
                //Req.AddParameterizedUrl

                // we need to serialize the cart and it items to xml here
                // so when we get it back from google
                // we can validate against the existing cart
                // as its possible items were added to the cart
                // after we passed the user to google

                //Req.MerchantPrivateData = cart.CartGuid.ToString();
                //cart.SerializeCartProducts();
                //Req.MerchantPrivateData = SerializationHelper.SerializeToSoap(cart);

                cart.SerializeCartProducts();
                MerchantData merchantData = new MerchantData
                                                {
                                                    ProviderName = "eStoreGCheckoutNotificationHandlerProvider",
                                                    SerializedObject =
                                                        SerializationHelper.RemoveXmlDeclaration(
                                                            SerializationHelper.SerializeToString(cart))
                                                };
                Req.MerchantPrivateData = SerializationHelper.RemoveXmlDeclaration(SerializationHelper.SerializeToString(merchantData));
                Req.RequestBuyerPhoneNumber = true;

                // flat rate shipping example
                //Req.AddFlatRateShippingMethod("UPS Ground", 5);

                //Add a rule to tax all items at 7.5% for Ohio
                //Req.AddStateTaxRule("NC", .15, true);
                //TODO: lookup tax 

                GCheckoutResponse Resp = Req.Send();

                if (Resp.IsGood)
                {
                    Response.Redirect(Resp.RedirectUrl, true);
                }
                else
                {
                    lblMessage.Text = Resp.ErrorMessage;
                }
            }

        }


        private void PopulateLabels()
        {
            Title = SiteUtils.FormatPageTitle(siteSettings, CurrentPage.PageName + " - " + eStoreResources.CartHeader);
            moduleTitle.Header = eStoreResources.CartHeader;

            lnkCheckout.Text = eStoreResources.ProceedToCheckout;
            lnkCheckout.NavigateUrl = SiteRoot + 
                "/eStore/ConfirmOrder.aspx?pageid=" + pageId.ToInvariantString()
                + "&mid=" + moduleId.ToInvariantString();
            btnOrder.PostBackUrl = SiteRoot + 
                "/eStore/ConfirmOrder.aspx?pageid=" + pageId.ToInvariantString()
                + "&mid=" + moduleId.ToInvariantString();
            btnOrder.Text = eStoreResources.ContinueButton;
            btnKeepShopping.Text = eStoreResources.CartKeepShoppingLink;
            btnKeepShopping.PostBackUrl = SiteUtils.GetCurrentPageUrl();

            litOr.Text = eStoreResources.LiteralOr;
            btnApplyDiscount.Text = eStoreResources.ApplyDiscountButton;

            lblDiscountError.Text = string.Empty;
            pnlStoreManager.CssClass += " " + config.CustomCssClassSetting + "-cart";
        }

        private void LoadParams()
        {

            pageId = WebUtils.ParseInt32FromQueryString("pageid", pageId);
            moduleId = WebUtils.ParseInt32FromQueryString("mid", true, moduleId);


        }

        private void ConfigureCheckoutButtons()
        {
            bool shouldShowPayPal = ShouldShowPayPal();
            bool shouldShowGoogle = ShouldShowGoogle();

            btnPayPal.Visible = shouldShowPayPal;
            btnGoogleCheckout.Visible = shouldShowGoogle;
            litOr.Visible = (shouldShowPayPal || shouldShowGoogle);

            if (shouldShowGoogle)
            {
                if ((!commerceConfig.Is503TaxExempt) && (cart.HasDonations()))
                {
                    lblGoogleMessage.Text = eStoreResources.GoogleCheckoutDisabledForDonationsMessage;
                    lblGoogleMessage.Visible = true;
                    btnGoogleCheckout.Enabled = false;
                    if (!Request.IsAuthenticated)
                    {
                        PaymentAcceptanceMark mark = pam1;
                        mark.SuppressGoogleCheckout = true;
                    }
                }

            }

            if ((shouldShowPayPal) && (commerceConfig.PayPalUsePayPalStandard))
            {
                SetupPayPalStandardForm();
            }
            //if we can't process cards internally there is no reason to go to the ConfirmOrder.aspx page 
            //and the order can be processed wtithout the user signing in or if the user is already signed in
            if (
                (!commerceConfig.CanProcessStandardCards)
                && ((Request.IsAuthenticated) || (canCheckoutWithoutAuthentication))
                )
            {
                lnkCheckout.Visible = false;
            }


        }



        private void LoadSettings()
        {
            commerceConfig = SiteUtils.GetCommerceConfig();
            //currencyCulture = CultureInfo.CurrentCulture;
            if (Request.IsAuthenticated)
            {
                siteUser = SiteUtils.GetCurrentSiteUser();
            }

            if (CurrentPage.ContainsModule(moduleId))
            {
                store = StoreHelper.GetStore();
            }

            if (store == null)
            {
                lnkCheckout.Visible = false;
                pnlDiscountCode.Visible = false;
                return;
            }

            if (
                (StoreHelper.UserHasCartCookie(store.Guid))
                || (Request.IsAuthenticated)
                )
            {
                cart = StoreHelper.GetCart();
            }

            if (cart == null)
            {
                pnlDiscountCode.Visible = false;
                lnkCheckout.Visible = false;
                return;
            }

            if ((cart.LastModified < DateTime.UtcNow.AddDays(-1)) && (cart.DiscountCodesCsv.Length > 0))
            {
                StoreHelper.EnsureValidDiscounts(store, cart);
            }

            if (store != null)
            {
                canCheckoutWithoutAuthentication = store.CanCheckoutWithoutAuthentication(cart);
            }

            // disable till I finish
            //canCheckoutWithoutAuthentication = false;

            ConfigureCheckoutButtons();

            int countOfDiscountCodes = Discount.GetCountOfActiveDiscountCodes(store.ModuleGuid);
            pnlDiscountCode.Visible = (countOfDiscountCodes > 0);

            // don't show the discount code panel if the cart is empty
            if (cart.SubTotal == 0)
            {
                lnkCheckout.Visible = false;
                //litOr.Visible = false;
                //btnPayPal.Visible = false;
                //btnGoogleCheckout.Visible = false;
                pnlDiscountCode.Visible = false;
            }

            //if (!Page.IsPostBack)
            //{
            //    if ((commerceConfig.PayPalIsEnabled) && (commerceConfig.PayPalUsePayPalStandard))
            //    {
            //        if (Request.IsAuthenticated)
            //        {
            //            siteUser = SiteUtils.GetCurrentSiteUser();
            //            SetupPayPalStandardForm();
            //        }
            //        else
            //        {
            //            //TODO: if the cart has no download items allow checkout without registration/sign in

            //            // we need the user to be signed in before we send them to paypal if using PayPal Standard
            //            // because we want to return them to their order summary and that requires login
            //            // so we need to know who the user is before sending them to PayPal
            //            litOr.Visible = false;
            //            btnPayPal.Visible = false;
            //            btnGoogleCheckout.Visible = false;
            //        }
            //    }
            //}




            //if (!Request.IsAuthenticated)
            //{


            //    if (commerceConfig.GoogleCheckoutIsEnabled)
            //    {
            //        if (
            //        (!commerceConfig.Is503TaxExempt)
            //        && (cart != null)
            //        && (cart.HasDonations())
            //        )
            //        {
            //            lblGoogleMessage.Text = eStoreResources.GoogleCheckoutDisabledForDonationsMessage;
            //            lblGoogleMessage.Visible = true;
            //            PaymentAcceptanceMark mark = (PaymentAcceptanceMark)pam1;
            //            mark.SuppressGoogleCheckout = true;

            //            btnGoogleCheckout.Visible = true;
            //            btnGoogleCheckout.Enabled = false;
            //        }
            //    }
            //}
            //else
            //{
            //    if (
            //        (!commerceConfig.Is503TaxExempt)
            //        && (cart != null)
            //        && (cart.HasDonations())
            //        && (commerceConfig.GoogleCheckoutIsEnabled)
            //        )
            //    {
            //        btnGoogleCheckout.Visible = true;
            //        btnGoogleCheckout.Enabled = false;
            //        lblGoogleMessage.Text = eStoreResources.GoogleCheckoutDisabledForDonationsMessage;
            //        lblGoogleMessage.Visible = true;
            //    }


            //}




        }

        private bool ShouldShowPayPal()
        {
            if (store == null) { return false; }
            if (cart == null) { return false; }
            if (cart.SubTotal == 0) { return false; }
            if (cart.OrderTotal == 0) { return false; }
            if (commerceConfig == null) { return false; }
            if ((!Request.IsAuthenticated) && (!canCheckoutWithoutAuthentication)) { return false; }
            if (!commerceConfig.PayPalIsEnabled) { return false; }



            return true;
        }

        private bool ShouldShowGoogle()
        {
            if (store == null) { return false; }
            if (cart == null) { return false; }
            if (cart.SubTotal == 0) { return false; }
            if (cart.OrderTotal == 0) { return false; }
            if (commerceConfig == null) { return false; }
            if ((!Request.IsAuthenticated) && (!canCheckoutWithoutAuthentication)) { return false; }
            if (!commerceConfig.GoogleCheckoutIsEnabled) { return false; }

            return true;
        }

        protected virtual void SetupCss()
        {
            // older skins have this
            if (Page.Master == null) return;
            StyleSheet stylesheet = (StyleSheet)Page.Master.FindControl("StyleSheet");
            if (stylesheet == null) return;
            if (stylesheet.FindControl("styleestore") != null) return;
            Literal cssLink = new Literal
            {
                ID = "styleestore",
                Text = @"<link href='"
                       + SiteUtils.GetSkinBaseUrl()
                       +
                       @"styleestore.css' type='text/css' rel='stylesheet' media='screen' />"
            };

            stylesheet.Controls.Add(cssLink);
        }

        void rptCartItems_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            mojoButton btnDelete = e.Item.FindControl("btnDelete") as mojoButton;
            mojoButton btnDeleteAlt = e.Item.FindControl("btnDeleteAlt") as mojoButton;
            if (btnDelete != null)
            {
                UIHelper.AddConfirmationDialog(btnDelete, eStoreResources.DownloadTermsDeleteWarning);
            }
            if (btnDeleteAlt != null)
            {
                UIHelper.AddConfirmationDialog(btnDeleteAlt, eStoreResources.DownloadTermsDeleteWarning);
            }
        }


        #region OnInit

        protected override void OnPreInit(EventArgs e)
        {
            AllowSkinOverride = true;
            base.OnPreInit(e);
        }

        protected override void OnInit(EventArgs e)
        {
            LoadParams();
            LoadPanels();
            base.OnInit(e);

            Load += Page_Load;
            rptCartItems.ItemCommand += rptCartItems_ItemCommand;

            btnPayPal.Click += btnPayPal_Click;
            btnGoogleCheckout.Click += btnGoogleCheckout_Click;
            btnApplyDiscount.Click += btnApplyDiscount_Click;
            rptCartItems.ItemDataBound += rptCartItems_ItemDataBound;
            SuppressPageMenu();
            SuppressGoogleAds();
        }

        private void LoadPanels()
        {
            Hashtable settings = ModuleSettings.GetModuleSettings(moduleId);
            config = new eStoreConfiguration(settings);
            LoadSideContent(config.ShowLeftPanelSetting, config.ShowRightPanelSetting, config.ShowTopPanelSetting, config.ShowBottomPanelSetting, config.ShowCenterPanelSetting);
        }
        #endregion
    }
}
